import json
import re

from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from django.contrib.auth import login
from django.http import HttpResponse
from django.http import HttpResponseForbidden
from django.http import JsonResponse
from django.shortcuts import render, redirect

# Create your views here.
from django.views import View
from django_redis import get_redis_connection

from meiduo_mall import dev
from oauth.utils import decode_openid, encode_openid
from user.models import User
from utils import sinaweibopy3
from .models import OAuthQQUser, OAuthSinaUser


class QQAuthURLView(View):
    def get(self, request):
        oauth = OAuthQQ(client_id=dev.QQ_CLIENT_ID, client_secret=dev.QQ_CLIENT_SECRET,
                        redirect_uri=dev.QQ_REDIRECT_URI, state=next)
        login_url = oauth.get_qq_url()
        return redirect(login_url)


class OAuthUserView(View):
    def get(self, request):
        # 1.接收数据
        code = request.GET.get('code')
        state = request.GET.get('state', '/')
        # 2.检验数据
        if not code:
            return HttpResponseForbidden('code丢失')

        # 3.处理业务
        oauth_qq = OAuthQQ(client_id=dev.QQ_CLIENT_ID, client_secret=dev.QQ_CLIENT_SECRET,
                           redirect_uri=dev.QQ_REDIRECT_URI, state=next)
        access_token = oauth_qq.get_access_token(code)

        openid = oauth_qq.get_open_id(access_token)

        try:
            user_openid = OAuthQQUser.objects.get(openid=openid)
        except Exception as e:
            print(e)
            sign_openid = encode_openid(openid)
            context = {
                'openid': sign_openid,
            }
            return render(request, 'oauth_callback.html', context=context)
        user = user_openid.user
        login(request, user)
        # 保持状态
        response = redirect('/')
        request.session.set_expiry(None)
        response.set_cookie('username', user.username, expires=3600 * 24 * 14)
        # 4.返回响应
        return response

    def post(self, request):
        # 1.接收数据
        sign_open_id = request.POST.get('openid')
        mobile = request.POST.get('mobile')
        pwd = request.POST.get('pwd')
        sms_code = request.POST.get('sms_code')
        # 2.检验数据
        # 2.1判断是否为空
        if not all([sign_open_id, mobile, pwd, sms_code]):
            return HttpResponseForbidden('参数不全')
        # 2.2 校验sign_openid是否正确
        open_id = decode_openid(sign_open_id)
        if not open_id:
            return HttpResponseForbidden('openid过期')
        # 2.3校验输入内容
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseForbidden('手机号格式错误')
        if not re.match(r'^[0-9a-zA-Z]{8,20}$', pwd):
            return HttpResponseForbidden('密码格式错误')
        redis_conn = get_redis_connection('verify_code')
        redis_sms_code = redis_conn.get(mobile)
        if not redis_sms_code:
            return HttpResponseForbidden('短信验证码已过期')
        if sms_code != redis_sms_code.decode():
            return HttpResponseForbidden('短信验证码填写错误')
        # 3.处理业务
        # 根据手机号获取已注册用户
        try:
            user = User.objects.get(mobile=mobile)
        except Exception as e:
            # 3.1创建user
            user = User.objects.create_user(username=mobile, password=pwd, mobile=mobile)

        if user.check_password(raw_password=pwd):
            # 3.2绑定openid
            OAuthQQUser.objects.create(user=user, openid=open_id)
            # 3.3登陆
            login(request, user)
            # 3.4保持状态
            response = redirect('/')
            request.session.set_expiry(None)
            response.set_cookie('username', user.username, expires=3600 * 24 * 14)
            # 4.返回响应
            return response
        else:
            return HttpResponseForbidden('密码不正确')


class SinaAuthURLView(View):
    def get(self, request):
        client = sinaweibopy3.APIClient(app_key=settings.APP_KEY, app_secret=settings.APP_SECRET,
                                        redirect_uri=settings.REDIRECT_URL)
        login_url = client.get_authorize_url()
        return redirect(login_url)


class SinaOAuthUserView(View):
    def get(self, request):
        # 1.接收数据
        code = request.GET.get('code')
        state = request.GET.get('state', '/')
        # 2.检验数据
        if not code:
            return HttpResponseForbidden('code丢失')

        # 3.处理业务
        client = sinaweibopy3.APIClient(app_key=settings.APP_KEY, app_secret=settings.APP_SECRET,
                                        redirect_uri=settings.REDIRECT_URL)
        result = client.request_access_token(code)
        access_token = result.access_token
        uid = result.uid
        try:
            user_openid = OAuthSinaUser.objects.get(uid=uid)
        except Exception as e:
            print(e)
            sign_uid = encode_openid(uid)
            context = {
                'uid': sign_uid,
            }
            return render(request, 'sina_callback.html', context=context)
        user = user_openid.user
        login(request, user)
        # 保持状态
        response = redirect('/')
        request.session.set_expiry(None)
        response.set_cookie('username', user.username, expires=3600 * 24 * 14)
        # 4.返回响应
        return response


class SinaBindUserView(View):
    def post(self, request):
        """
        password: this.password,
        mobile: this.mobile,
        sms_code: this.sms_code,
        access_token: this.access_token
        """
        # 1.接收数据
        data = json.loads(request.body.decode())
        password = data['password']
        mobile = data['mobile']
        sms_code = data['sms_code']
        access_token = data['access_token']

        # 2.检验数据
        # 校验基本信息
        if not all([access_token, mobile, password, sms_code]):
            return HttpResponseForbidden('参数不全')
        open_id = decode_openid(access_token)
        if not open_id:
            return HttpResponseForbidden('openid过期')
        # redis_cline.setex(mobile, constants.REDIS_SMS_CODE_EXPIRE, sms_code)
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseForbidden('手机号格式错误')
        if not re.match(r'^[0-9a-zA-Z]{8,20}$', password):
            return HttpResponseForbidden('密码格式错误')
        # 校验短信验证码
        redis_conn = get_redis_connection('verify_code')
        redis_sms_code = redis_conn.get(mobile)
        if not redis_sms_code:
            return HttpResponseForbidden('短信验证码已过期')
        if sms_code != redis_sms_code.decode():
            return HttpResponseForbidden('短信验证码填写错误')
        # 3.处理业务
        uid = decode_openid(access_token)

        try:
            user = User.objects.get(mobile=mobile)
        except:
            user = User.objects.create_user(mobile, password=password)
        if user.check_password(raw_password=password):
            OAuthSinaUser.objects.create(user=user, uid=uid)
            login(request,user)
            """
            localStorage.token = response.data.token;
            localStorage.user_id = response.data.user_id;
            localStorage.username = response.data.username;"""
            res = {
                'token':encode_openid(uid),
                'user_id':user.id,
                'username':user.username
            }
            response = JsonResponse(res)
            request.session.set_expiry(None)
            response.set_cookie('username', user.username, expires=3600 * 24 * 14)
            # 4.返回响应
            return response
        else:
            return HttpResponseForbidden('密码不正确')